# 多线程程序的好处：可以为相关阻塞的操作单独开启线程或进程，阻塞操作就可以异步执行。
# 线程池、进程池的好处：我们可以降低系统对进程或者现成创建和销毁的频率，从而很好的降低系统的开销。

# 多进程案例：爬取梨视频的视频数据

import requests
import time

# 导入线程池模块儿对应的类
from multiprocessing.dummy import Pool
from lxml import etree

start_time = time.time()

# 用来存储视频链接、视频名称
video_msg = []

# 01. 指定 url
url = 'https://pearvideo.com/category_1'

# 02. 发起请求，使用 get 方法发起 get 请求，该方法回返回一个响应对象。参数 url 表示请求相应的 url。
headers = {
    "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36"
}


# 03. 获取响应数据：通过调用响应对象的 text 属性，返回响应对象中存储的字符串形式的响应数据（页面源码数据）
def get_video_mag(ww):
    print('正在爬取：', url)
    resp = requests.get(url, headers=headers)
    resp.encoding = 'utf-8'
    resp.close()
    if resp.status_code == 200:
        tree = etree.HTML(resp.content)
        # 获取视频所在的标签
        li_list = tree.xpath('//ul[@id="listvideoListUl"]/li')

        for li in li_list:
            detail_url = 'https://pearvideo.com/' + li.xpath('./div/a/@href')[0]
            name = li.xpath('./div/a/div[2]/text()')[0]
            print(name, ': ', detail_url)

            # 1. 拿到 contId
            # 'https://pearvideo.com/video_1679537'
            contId = detail_url.split('_')[1]
            print('contId: ', contId)

            # 2. 拿到 videoStatus 返回的 json -> srcURL
            videoStatus = f'https://pearvideo.com/videoStatus.jsp?contId={contId}&mrd=0.7631135027610461'
            heads = {
                'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36',
                # 防盗链：溯源，本次请求的上一个请求是谁
                'Referer': f'https://pearvideo.com/video_{contId}'
            }

            resp = requests.get(videoStatus, headers=heads)
            resp.close()

            print('返回json: ', resp.text)

            # 3. srcURL 里面的内容进行修正
            dic = resp.json()
            srcURL = dic['videoInfo']['videos']['srcUrl']
            systemTime = dic['systemTime']
            srcURL = srcURL.replace(systemTime, 'cont-' + contId)

            print('mp4-URL: ', srcURL)

            video_dic = {
                'name': name,
                'url': srcURL
            }
            video_msg.append(video_dic)


# 4. 下载视频
def download_video(video_dic):
    video_name = video_dic['name']
    video_url = video_dic['url']
    with open(f'./梨视频/{video_name}.mp4', mode='wb') as file:
        print(video_name, '.mp4，下载中······')
        file.write(requests.get(video_url).content)
        file.close()
    print(video_name, '.mp4，下载成功！')


if __name__ == '__main__':
    # 单线程方式
    # for url in urls:
    #     content_msg = get_content(url)
    #     length_msg = parse_content(content_msg)

    # 使用线程池对视频数据进行请求（较为耗时的阻塞操作）
    # get_video_mag()
    # pool = Pool(4)
    # pool.map(download_video, video_msg)

    # 创建线程池
    pool = Pool(4)
    pool.map(get_video_mag, '0')
    pool.map(download_video, video_msg)

    # 感觉爬取效率没提升多少啊

    # 等待线程池中的任务全部执行完毕，才会继续执行守护线程
    print('over!')

    # 查看耗时
    end_time = time.time()
    print(end_time - start_time)
